package tms.util.jsf;

import tms.util.constants.CookieParameter;
import tms.util.constants.NavigationConstant;
import tms.util.constants.RequestParameter;

import javax.el.ELContext;
import javax.el.ExpressionFactory;
import javax.enterprise.context.RequestScoped;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.inject.Named;
import javax.servlet.http.Cookie;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Named
@RequestScoped
public class FacesContextManager implements Serializable {
    private static final String REDIRECT_SURVIVE_MESSAGES = "REDIRECT_SURVIVE_MESSAGES";

    public FacesContext getFacesContext() {
        return FacesContext.getCurrentInstance();
    }

    public ExternalContext getExternalContext() {
        return getFacesContext().getExternalContext();
    }

    public UIViewRoot getViewRoot() {
        return getFacesContext().getViewRoot();
    }

    public FacesMessage buildFacesMessage(String summary) {
        return new FacesMessage(summary);
    }

    public void navigateForOutcome(NavigationConstant navigationConstant) {
        getFacesContext().getApplication().getNavigationHandler().handleNavigation(getFacesContext(), null, navigationConstant.name());
    }

    public void addMessage(String summary) {
        getFacesContext().addMessage(null, buildFacesMessage(summary));    
    }

    @SuppressWarnings("unchecked")
    public void addRedirectSurviveMessage(String summary) {
        Object o = getExternalContext().getSessionMap().get(REDIRECT_SURVIVE_MESSAGES);
        if (o == null) {
            o = new ArrayList<FacesMessage>();
            getExternalContext().getSessionMap().put(REDIRECT_SURVIVE_MESSAGES, o);
        }
        List<FacesMessage> messages = (List<FacesMessage>)o;
        messages.add(buildFacesMessage(summary));
    }

    @SuppressWarnings("unchecked")
    public List<FacesMessage> getRedirectSurviveMessages() {
        Object o = getExternalContext().getSessionMap().remove(REDIRECT_SURVIVE_MESSAGES);
        if (o == null) {
            o = new ArrayList<FacesMessage>(0);
        }
        return (List<FacesMessage>)o;
    }

    public String getContextPath() {
        return getExternalContext().getRequestContextPath();
    }

    public String getRequestParameter(RequestParameter parameter) {
        String retVal = getExternalContext().getRequestParameterMap().get(parameter.value());
        if (retVal != null) {
            return retVal;
        } else {
            return "";
        }
    }

    public String getCookieParameter(CookieParameter parameter) {
        Cookie cookie = (Cookie)getExternalContext().getRequestCookieMap().get(parameter.name());
        if (cookie != null) {
            return cookie.getValue();
        } else {
            return "";
        }
    }

    public void addCookie(CookieParameter parameter, String value, int age) {
        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put("maxAge", age);
        properties.put("path", "/");
        getExternalContext().addResponseCookie(parameter.name(), value, properties);
    }

    @SuppressWarnings("unchecked")
    public <T> T evaluateExpression(String expression, Class<T> clazz) {
        ELContext elContext = FacesContext.getCurrentInstance().getELContext();
        Object retVal = ExpressionFactory.newInstance().
                        createValueExpression(elContext, expression, clazz).
                        getValue(elContext);
        if (retVal == null || retVal.getClass() != clazz) {
            retVal = null;
        }
        return (T)retVal;
    }
}
